import time
import logging
import threading
from typing import Dict, Any, Optional, Callable, List
from queue import Queue
import weakref
from ..utils.config_loader import ConfigLoader

class ResourcePool:
    """
    资源池基类，管理可复用资源
    """
    
    def __init__(self, max_size: int, create_func: Callable, destroy_func: Callable):
        """
        初始化资源池
        
        Args:
            max_size: 最大资源数量
            create_func: 创建资源的函数
            destroy_func: 销毁资源的函数
        """
        self.max_size = max_size
        self.create_func = create_func
        self.destroy_func = destroy_func
        self.pool = Queue(maxsize=max_size)
        self.active_resources = 0
        self.lock = threading.RLock()
        self.logger = logging.getLogger('ResourcePool')
    
    def get(self, timeout: float = None) -> Any:
        """
        从池中获取资源
        
        Args:
            timeout: 超时时间
            
        Returns:
            资源对象
        """
        with self.lock:
            # 首先尝试从队列获取
            try:
                resource = self.pool.get(block=False)
                self.logger.debug(f"从池中获取资源成功，池剩余: {self.pool.qsize()}")
                return resource
            except Exception:
                # 池为空，尝试创建新资源
                if self.active_resources < self.max_size:
                    try:
                        resource = self.create_func()
                        self.active_resources += 1
                        self.logger.debug(f"创建新资源成功，活动资源数: {self.active_resources}")
                        return resource
                    except Exception as e:
                        self.logger.error(f"创建资源失败: {str(e)}")
                        raise
                else:
                    # 达到最大资源数，等待资源释放
                    try:
                        resource = self.pool.get(block=True, timeout=timeout)
                        self.logger.debug(f"等待后获取资源成功，池剩余: {self.pool.qsize()}")
                        return resource
                    except Exception:
                        self.logger.error(f"获取资源超时")
                        raise TimeoutError("获取资源超时")
    
    def put(self, resource: Any, validate: bool = True):
        """
        归还资源到池中
        
        Args:
            resource: 资源对象
            validate: 是否验证资源有效性
        """
        with self.lock:
            try:
                # 验证资源有效性
                if validate and hasattr(resource, 'is_valid'):
                    if not resource.is_valid():
                        self.logger.warning("资源无效，将被销毁")
                        self._destroy_resource(resource)
                        return
                
                # 尝试放回池中
                self.pool.put(resource, block=False)
                self.logger.debug(f"资源归还成功，池大小: {self.pool.qsize()}")
            except Exception:
                # 池已满，销毁资源
                self.logger.warning("资源池已满，销毁多余资源")
                self._destroy_resource(resource)
    
    def _destroy_resource(self, resource: Any):
        """
        销毁资源
        
        Args:
            resource: 资源对象
        """
        try:
            self.destroy_func(resource)
            with self.lock:
                self.active_resources -= 1
            self.logger.debug(f"资源销毁成功，剩余活动资源数: {self.active_resources}")
        except Exception as e:
            self.logger.error(f"销毁资源失败: {str(e)}")
    
    def clear(self):
        """
        清空资源池
        """
        with self.lock:
            while not self.pool.empty():
                try:
                    resource = self.pool.get(block=False)
                    self._destroy_resource(resource)
                except Exception:
                    pass
            self.logger.info("资源池已清空")
    
    def get_stats(self) -> Dict[str, int]:
        """
        获取资源池统计信息
        
        Returns:
            统计信息
        """
        with self.lock:
            return {
                'active_resources': self.active_resources,
                'pool_size': self.pool.qsize(),
                'max_size': self.max_size,
                'available_slots': self.max_size - self.active_resources
            }

class ResourceManager:
    """
    资源管理器，管理多种测试资源的创建、复用和销毁
    """
    
    def __init__(self, config_path: str = None):
        """
        初始化资源管理器
        
        Args:
            config_path: 配置文件路径
        """
        # 加载配置
        self.config_loader = ConfigLoader(config_path)
        self.config = self.config_loader.get_config()['resource_manager']
        
        # 资源池配置
        self.pool_enabled = self.config['pool_enabled']
        self.max_pool_size = self.config['max_pool_size']
        self.connection_timeout = self.config['connection_timeout']
        self.reuse_threshold = self.config['reuse_threshold']
        self.cleanup_interval = self.config['cleanup_interval']
        
        # 资源池字典
        self.resource_pools: Dict[str, ResourcePool] = {}
        
        # 资源使用统计
        self.resource_stats = {
            'total_created': 0,
            'total_reused': 0,
            'total_destroyed': 0,
            'reuse_savings': 0  # 估计的时间节省（秒）
        }
        
        # 资源创建时间记录
        self.resource_creation_times: Dict[str, float] = {}
        
        # 锁和线程安全
        self.lock = threading.RLock()
        
        # 清理线程
        self.cleanup_thread = None
        self.running = True
        
        # 初始化日志
        logging.basicConfig(
            level=getattr(logging, self.config_loader.get_config()['logging']['level']),
            format=self.config_loader.get_config()['logging']['format']
        )
        self.logger = logging.getLogger('ResourceManager')
        
        # 启动清理线程
        if self.cleanup_interval > 0:
            self._start_cleanup_thread()
        
        self.logger.info("资源管理器初始化完成")
    
    def register_resource_type(self, resource_type: str, create_func: Callable, 
                             destroy_func: Callable, max_size: int = None):
        """
        注册资源类型
        
        Args:
            resource_type: 资源类型标识
            create_func: 创建资源的函数
            destroy_func: 销毁资源的函数
            max_size: 最大资源数量，None使用默认值
        """
        with self.lock:
            if resource_type in self.resource_pools:
                self.logger.warning(f"资源类型 {resource_type} 已注册")
                return
            
            # 创建带统计的创建函数
            def create_with_stats():
                start_time = time.time()
                resource = create_func()
                creation_time = time.time() - start_time
                
                with self.lock:
                    self.resource_stats['total_created'] += 1
                    self.resource_creation_times[resource_type] = creation_time
                    self.logger.debug(f"创建资源 {resource_type} 耗时: {creation_time:.3f}秒")
                
                return resource
            
            # 创建资源池
            pool_size = max_size if max_size is not None else self.max_pool_size
            self.resource_pools[resource_type] = ResourcePool(
                max_size=pool_size,
                create_func=create_with_stats if self.pool_enabled else create_func,
                destroy_func=destroy_func
            )
            
            self.logger.info(f"资源类型 {resource_type} 注册成功，最大数量: {pool_size}")
    
    def get_resource(self, resource_type: str, timeout: float = None) -> Any:
        """
        获取指定类型的资源
        
        Args:
            resource_type: 资源类型
            timeout: 超时时间
            
        Returns:
            资源对象
        """
        if resource_type not in self.resource_pools:
            raise ValueError(f"未注册的资源类型: {resource_type}")
        
        start_time = time.time()
        resource = self.resource_pools[resource_type].get(timeout=timeout)
        
        # 记录复用节省的时间
        with self.lock:
            if self.pool_enabled and resource_type in self.resource_creation_times:
                self.resource_stats['total_reused'] += 1
                # 复用资源节省了创建时间
                reuse_time = time.time() - start_time
                creation_time = self.resource_creation_times[resource_type]
                savings = creation_time - reuse_time
                if savings > 0:
                    self.resource_stats['reuse_savings'] += savings
                
                self.logger.debug(f"复用资源 {resource_type} 节省时间: {savings:.3f}秒")
        
        return resource
    
    def release_resource(self, resource_type: str, resource: Any, validate: bool = True):
        """
        释放资源回池中
        
        Args:
            resource_type: 资源类型
            resource: 资源对象
            validate: 是否验证资源有效性
        """
        if resource_type not in self.resource_pools:
            raise ValueError(f"未注册的资源类型: {resource_type}")
        
        self.resource_pools[resource_type].put(resource, validate=validate)
    
    def _start_cleanup_thread(self):
        """
        启动资源清理线程
        """
        def cleanup_task():
            while self.running:
                try:
                    time.sleep(self.cleanup_interval)
                    self._cleanup_idle_resources()
                except Exception as e:
                    self.logger.error(f"清理线程异常: {str(e)}")
        
        self.cleanup_thread = threading.Thread(target=cleanup_task, daemon=True)
        self.cleanup_thread.start()
        self.logger.info(f"资源清理线程已启动，清理间隔: {self.cleanup_interval}秒")
    
    def _cleanup_idle_resources(self):
        """
        清理空闲资源
        """
        # TODO: 实现更智能的资源清理策略
        # 目前只是记录状态
        for resource_type, pool in self.resource_pools.items():
            stats = pool.get_stats()
            self.logger.debug(f"资源类型 {resource_type} 状态: {stats}")
    
    def get_stats(self) -> Dict[str, Any]:
        """
        获取资源管理器统计信息
        
        Returns:
            统计信息
        """
        with self.lock:
            pool_stats = {}
            for resource_type, pool in self.resource_pools.items():
                pool_stats[resource_type] = pool.get_stats()
            
            return {
                'resource_stats': self.resource_stats.copy(),
                'pool_stats': pool_stats,
                'pool_enabled': self.pool_enabled,
                'estimated_efficiency_improvement': self._calculate_efficiency_improvement()
            }
    
    def _calculate_efficiency_improvement(self) -> float:
        """
        计算资源复用带来的效率提升
        
        Returns:
            效率提升百分比
        """
        if self.resource_stats['total_created'] == 0:
            return 0
        
        # 基于节省的时间计算效率提升
        if self.resource_stats['reuse_savings'] > 0:
            # 假设创建所有资源的总时间
            total_creation_time = sum(
                self.resource_creation_times.get(rt, 0) * self.resource_stats['total_created']
                for rt in self.resource_creation_times
            ) / len(self.resource_creation_times) if self.resource_creation_times else 0
            
            if total_creation_time > 0:
                # 计算百分比提升
                improvement = (self.resource_stats['reuse_savings'] / total_creation_time) * 100
                return min(improvement, 100)  # 限制最大提升为100%
        
        # 基于复用率计算
        reuse_rate = (self.resource_stats['total_reused'] / 
                     (self.resource_stats['total_created'] + self.resource_stats['total_reused'])) * 100
        return reuse_rate
    
    def shutdown(self):
        """
        关闭资源管理器，释放所有资源
        """
        self.logger.info("正在关闭资源管理器...")
        
        # 停止清理线程
        self.running = False
        if self.cleanup_thread:
            self.cleanup_thread.join(timeout=5)
        
        # 清空所有资源池
        for resource_type, pool in self.resource_pools.items():
            self.logger.info(f"清空资源类型 {resource_type} 的池")
            pool.clear()
        
        self.logger.info("资源管理器已关闭")

# 全局资源管理器实例
_resource_manager_instance = None
_instance_lock = threading.RLock()

def get_resource_manager(config_path: str = None) -> ResourceManager:
    """
    获取全局资源管理器实例
    
    Args:
        config_path: 配置文件路径
        
    Returns:
        ResourceManager实例
    """
    global _resource_manager_instance
    with _instance_lock:
        if _resource_manager_instance is None:
            _resource_manager_instance = ResourceManager(config_path)
    return _resource_manager_instance

# 便捷函数
def register_resource(resource_type: str, create_func: Callable, 
                     destroy_func: Callable, max_size: int = None):
    """便捷函数：注册资源类型"""
    return get_resource_manager().register_resource_type(
        resource_type, create_func, destroy_func, max_size
    )

def get_resource(resource_type: str, timeout: float = None) -> Any:
    """便捷函数：获取资源"""
    return get_resource_manager().get_resource(resource_type, timeout)

def release_resource(resource_type: str, resource: Any):
    """便捷函数：释放资源"""
    return get_resource_manager().release_resource(resource_type, resource)